import tkinter as tk
from tkinter import messagebox
import cv2
from src.pose_estimation import PoseProcessor
import time
from PIL import Image, ImageTk, ImageStat
import os
from src.capture import VideoCapture
from src.detection import HumanDetector

#智能健身指导系统UI界面类
class FitnessUI:
    """智能健身指导系统UI界面"""
    def __init__(self, root):
        self.root = root
        self.root.title("智能健身指导系统")
        self.root.geometry("1200x700")  # 界面大小
        self.root.resizable(True, True)

        # 主窗口近不透明（避免完全透明影响可见性）
        self.root.wm_attributes("-alpha", 0.99)

        # 初始化核心组件
        self.cap = VideoCapture()
        self.pose_processor = PoseProcessor()
        self.human_detector = HumanDetector()  # 人体检测模块（独立）
        self.user_history = []  # 动作历史缓存
        self.feedback = "等待开始检测..."  # 反馈信息
        self.fps = 0  # 帧率

        # 先创建背景图（必须第一个创建，确保在最底层），同时计算“面板背景色”以便融入背景
        self._create_background()
        # 再创建其他组件（在背景图上方）
        self._create_widgets()

        # 启动更新循环
        self._update_loop()

    def _create_background(self):
        """设置背景图并计算用于上层面板的平均色"""
        try:
            # 动态获取背景图路径：项目根目录/data/drawable/background.jpg
            src_dir = os.path.dirname(os.path.abspath(__file__))  # 当前脚本所在目录
            root_dir = os.path.dirname(src_dir)  # 项目根目录
            bg_path = os.path.join(root_dir, "data", "drawable", "background.jpg")
            print(f"加载背景图路径：{bg_path}")

            # 打开图片
            self.bg_image = Image.open(bg_path).convert("RGBA")
            # 保存 PhotoImage 以便显示
            self.bg_photo = ImageTk.PhotoImage(self.bg_image)

            # 创建背景标签（置于最底层）
            self.bg_label = tk.Label(self.root, image=self.bg_photo)
            self.bg_label.place(x=0, y=0, relwidth=1, relheight=1)
            self.bg_label.image = self.bg_photo
            # 绑定窗口缩放事件
            self.root.bind("<Configure>", self._resize_background)

            # 计算平均颜色（用于上层面板背景，使其更融入背景）
            stat = ImageStat.Stat(self.bg_image.convert("RGB"))
            r, g, b = [int(x) for x in stat.mean]
            self.panel_bg = f"#{r:02x}{g:02x}{b:02x}"
            # 让 panel_bg 稍微亮一点（避免文字和控件看不清）
            def brighten(hexcol, factor=1.15):
                ri = int(hexcol[1:3], 16)
                gi = int(hexcol[3:5], 16)
                bi = int(hexcol[5:7], 16)
                ri = min(255, int(ri * factor))
                gi = min(255, int(gi * factor))
                bi = min(255, int(bi * factor))
                return f"#{ri:02x}{gi:02x}{bi:02x}"
            self.panel_bg = brighten(self.panel_bg, factor=1.08)

        except Exception as e:
            print(f"背景图加载失败：{str(e)}")
            # 失败时用蓝色背景（和你之前保持一致）
            self.root.configure(bg="#0000FF")
            self.panel_bg = "#e6f0ff"  # 一个浅蓝，用作上层面板背景

    def _resize_background(self, event):
        """窗口缩放时自适应背景图（如果背景加载成功）"""
        if hasattr(self, "bg_image"):
            # 忽略高度/宽度为0的事件（有时移动时会触发）
            if event.width <= 1 or event.height <= 1:
                return
            new_width = event.width
            new_height = event.height
            resized_image = self.bg_image.resize((new_width, new_height), Image.LANCZOS)
            self.bg_photo = ImageTk.PhotoImage(resized_image)
            self.bg_label.config(image=self.bg_photo)
            self.bg_label.image = self.bg_photo

    #创建所有上层组件
    def _create_widgets(self):
        # 主框架（使用 tk.Frame，可自定义背景色）
        main_frame = tk.Frame(self.root, bg=self.panel_bg, padx=10, pady=10)
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 使用 grid 来控制左右比例（3:2）
        main_frame.grid_columnconfigure(0, weight=3)
        main_frame.grid_columnconfigure(1, weight=2)
        main_frame.grid_rowconfigure(0, weight=1)

        # ---------------------- 左侧：实时视频区 ----------------------
        left_frame = tk.LabelFrame(
            main_frame,
            text="实时拍摄检测区",
            bg=self.panel_bg,
            padx=10,
            pady=10,
            fg="#4B0082",  # 标题颜色改为白色
            font=("Microsoft YaHei", 10,"bold")  # 字体 + 字号（可换 SimHei / 黑体 / 等）
        )
        #left_frame = tk.LabelFrame(main_frame, text="实时拍摄检测区", bg=self.panel_bg, padx=10, pady=10, fg="black")
        left_frame.grid(row=0, column=0, sticky=tk.NSEW, padx=(0, 10), pady=8)

        # 视频显示标签（设置与 panel_bg 匹配，使其更融入背景）
        self.video_label = tk.Label(left_frame, bg=self.panel_bg)
        self.video_label.pack(fill=tk.BOTH, expand=True)

        # 左侧底部控制按钮区
        left_controls = tk.Frame(left_frame, bg=self.panel_bg)
        left_controls.pack(fill=tk.X, pady=10)

        # 使用 ttk.Button 以保持统一外观（可以换成 tk.Button）
        import tkinter.ttk as ttk
        self.start_btn = ttk.Button(left_controls, text="开始检测", command=self._toggle_detection)
        self.start_btn.pack(side=tk.LEFT, padx=5)

        self.quit_btn = ttk.Button(left_controls, text="退出", command=self._quit)
        self.quit_btn.pack(side=tk.RIGHT, padx=5)

        # ---------------------- 右侧：功能区 ----------------------
        right_frame = tk.LabelFrame(
            main_frame,
            text="功能区",
            bg=self.panel_bg,
            padx=10,
            pady=10,
            fg="#4B0082",  # 标题颜色改为白色
            font=("Microsoft YaHei", 12,"bold")  # 字体 + 字号（可换 SimHei / 黑体 / 等）
        )
        # right_frame = tk.LabelFrame(main_frame, text="功能区", bg=self.panel_bg, padx=10, pady=10, fg="black")
        right_frame.grid(row=0, column=1, sticky=tk.NSEW, padx=(10, 0), pady=8)
        right_frame.grid_columnconfigure(0, weight=1)

        # 右侧1：标准模板对比（居中显示）
        # lbl_templates = tk.Label(right_frame, text="标准模板对比", font=("SimHei", 12), bg=self.panel_bg)
        lbl_templates = tk.Label(
            right_frame,
            text="标准模板对比",
            font=("SimHei", 14, "bold"),  # 字体稍加粗可读性更好
            bg=self.panel_bg,
            fg="white"  # 字体改白色更匹配深色背景
        )
        lbl_templates.pack(anchor=tk.W, pady=5)
        template_frame = tk.Frame(right_frame, bg=self.panel_bg)
        template_frame.grid_columnconfigure(0, weight=1)
        template_frame.grid_columnconfigure(1, weight=1)
        template_frame.pack(fill=tk.X, pady=10, anchor=tk.CENTER)

        # 加载标准模板图片
        self.template_icons = []
        template_names = ["picture1", "picture2", "picture3", "picture4"]
        for i in range(4):
            try:
                src_dir = os.path.dirname(os.path.abspath(__file__))
                root_dir = os.path.dirname(src_dir)
                img_path = os.path.join(root_dir, "data", "templates", f"{template_names[i]}.png")

                img = Image.open(img_path).resize((100, 120))
                img_tk = ImageTk.PhotoImage(img)

                btn = ttk.Button(
                    template_frame,
                    image=img_tk,
                    command=lambda idx=i: self._select_template(idx)
                )
                btn.image = img_tk  # 保留图片引用
                btn.grid(row=i // 2, column=i % 2, padx=20, pady=15, sticky=tk.NSEW)
                self.template_icons.append(btn)
            except Exception as e:
                # 若图片不存在，显示占位
                self._update_feedback(f"警告：未找到图片 {img_path}")
                img = Image.new("RGB", (100, 120), color=(200, 200, 200))
                img_tk = ImageTk.PhotoImage(img)
                btn = ttk.Button(template_frame, image=img_tk)
                btn.image = img_tk
                btn.grid(row=i // 2, column=i % 2, padx=20, pady=15)

        # 右侧2：实时反馈
        lbl_feedback = tk.Label(
            right_frame,
            text="实时反馈",
            font=("SimHei", 14, "bold"),  # 字体稍加粗可读性更好
            bg=self.panel_bg,
            fg="white"  # 字体改白色更匹配深色背景
        )
        lbl_feedback.pack(anchor=tk.W, pady=5)
        # self.feedback_text = tk.Text(right_frame, height=5, width=30, bg=self.panel_bg, bd=0)
        self.feedback_text = tk.Text(
            right_frame,
            height=4,
            width=30,
            bg="white",  # ← 改为白色背景
            fg="black",
            relief="solid",  # 有边框，看起来是一个独立的文本框
            bd=1,
            font=("Microsoft YaHei", 11)  # 字体更清晰
        )
        self.feedback_text.pack(fill=tk.X, pady=10)
        self._update_feedback("请点击【开始检测】启动摄像头")

        # 右侧3：功能按钮
        func_frame = tk.Frame(right_frame, bg=self.panel_bg)#tk.Frame 是一个容器，用来装控件
        func_frame.pack(fill=tk.X, pady=20)#pack 是控件布局方式

        self.voice_btn = ttk.Button(func_frame, text="开启语音播报", command=self._toggle_voice)
        '''
            ttk.Button 表示创建一个按钮（样式美观）
            func_frame 表示按钮放在功能按钮区域内
            text="开启语音播报" 按钮上显示的文字
            command=self._toggle_voice 表示点击按钮时，调用类中的 _toggle_voice() 方法
        '''
        self.voice_btn.pack(side=tk.LEFT, padx=10)
        '''
        side=tk.LEFT 表示按钮靠左放
        padx=10 表示左右间距为 10 像素(这里指的是与左边框)，让按钮之间不会贴太紧
        '''

        self.save_btn = ttk.Button(func_frame, text="保存错误帧", command=self._save_error_frame)
        self.save_btn.pack(side=tk.RIGHT, padx=10)

    # ---------------------- 以下方法保持不变 ----------------------
    def _toggle_detection(self):
        if self.cap.is_running:
            self.cap.stop()
            try:
                self.start_btn.config(text="开始检测")
            except Exception:
                pass
            self._update_feedback("已暂停检测")
        else:
            try:
                self.cap = VideoCapture()
                self.cap.start()
                try:
                    self.start_btn.config(text="暂停检测")
                except Exception:
                    pass
                self._update_feedback("正在检测...请做出健身动作")
            except Exception as e:
                messagebox.showerror("错误", str(e))

    def _select_template(self, idx):
        templates = ["深蹲", "弓步", "平板支撑", "俯卧撑"]
        self._update_feedback(f"已选择标准模板：{templates[idx]}")

    def _toggle_voice(self):
        current_text = self.voice_btn.config("text")[-1]
        if "开启" in current_text:
            self.voice_btn.config(text="关闭语音播报")
            self._update_feedback("语音播报已开启")
        else:
            self.voice_btn.config(text="开启语音播报")
            self._update_feedback("语音播报已关闭")

    def _save_error_frame(self):
        if hasattr(self, "current_frame") and self.current_frame is not None:
            filename = os.path.join(os.getcwd(), f"error_frame_{int(time.time())}.jpg")
            cv2.imwrite(filename, self.current_frame)
            self._update_feedback(f"错误帧已保存至: {filename}")
        else:
            self._update_feedback("无帧可保存，请先开始检测")

    def _update_feedback(self, text):
        self.feedback_text.config(state=tk.NORMAL)
        self.feedback_text.delete(1.0, tk.END)
        self.feedback_text.insert(tk.END, text)
        self.feedback_text.config(state=tk.DISABLED)

    def _update_loop(self):
        start_time = time.time()
        if self.cap.is_running:
            frame = self.cap.get_frame()
            if frame is not None:
                self.current_frame = frame.copy()
                frame_with_pose, results,coords = self.pose_processor.process(frame)
                elapsed = (time.time() - start_time)
                self.fps = 1 / elapsed if elapsed > 0 else 0
                cv2.putText(
                    frame_with_pose,
                    f"FPS: {int(self.fps)}",
                    (10, 30),
                    cv2.FONT_HERSHEY_SIMPLEX,
                    1,
                    (255, 0, 0),
                    2
                )
                frame_rgb = cv2.cvtColor(frame_with_pose, cv2.COLOR_BGR2RGB)
                img = Image.fromarray(frame_rgb)
                img_tk = ImageTk.PhotoImage(image=img)
                self.video_label.config(image=img_tk)
                self.video_label.image = img_tk
        self.root.after(30, self._update_loop)

    def _quit(self):
        try:
            self.cap.stop()
        except Exception:
            pass
        self.root.destroy()



